/**
 * 战斗结果生成器
 * 负责生成完整的战斗结果，包括统计数据、奖励分配等
 */

import { 
    BattleContext, 
    BattleResult, 
    BattleResultType, 
    BattleStatistics, 
    ParticipantStats 
} from './types';
import { ServiceLogger } from '../../../infrastructure/logging/UnifiedLogger';
import { BattleStateManager } from './BattleStateManager';
import { Item } from '../../../shared/face';

/**
 * 奖励配置
 */
interface RewardConfig {
    /** 基础经验值 */
    baseExperience: number;
    /** 经验加成倍数 */
    experienceMultiplier: number;
    /** 基础金币 */
    baseGold: number;
    /** 金币加成倍数 */
    goldMultiplier: number;
    /** 物品掉落概率 */
    itemDropChance: number;
    /** 最大掉落物品数 */
    maxDropItems: number;
}

/**
 * 战斗结果生成器
 */
export class BattleResultGenerator {
    private logger: ServiceLogger;
    private defaultRewardConfig: RewardConfig = {
        baseExperience: 100,
        experienceMultiplier: 1.0,
        baseGold: 50,
        goldMultiplier: 1.0,
        itemDropChance: 0.3,
        maxDropItems: 3
    };

    constructor() {
        this.logger = new ServiceLogger('BattleResultGenerator');
    }

    /**
     * 生成战斗结果
     */
    async generateResult(context: BattleContext): Promise<BattleResult> {
        const battleId = context.state.battleId;
        this.logger.info(`Generating battle result for: ${battleId}`);

        try {
            // 计算战斗统计
            const statistics = this.calculateStatistics(context);

            // 确定结果类型和获胜方
            const { resultType, winner } = this.determineResult(context);

            // 生成奖励
            const rewards = await this.generateRewards(context, resultType, winner);

            // 计算经验分配
            const experience = this.calculateExperience(context, resultType, winner);

            // 生成战斗报告
            const reportUrl = await this.generateBattleReport(context, statistics);

            const result: BattleResult = {
                battleId,
                resultType,
                winner,
                statistics,
                rewards,
                experience,
                reportUrl,
                completedAt: Date.now()
            };

            this.logger.info(`Battle result generated successfully`, {
                metadata: {
                    battleId,
                    resultType,
                    winner,
                    duration: statistics.duration,
                    totalRounds: statistics.totalRounds
                }
            });

            return result;

        } catch (error) {
            this.logger.error(`Failed to generate battle result for: ${battleId}`, undefined, error);
            
            // 返回错误结果
            return this.generateErrorResult(context, error as Error);
        }
    }

    /**
     * 计算战斗统计
     */
    private calculateStatistics(context: BattleContext): BattleStatistics {
        const participantStats = new Map<string, ParticipantStats>();
        const kills: Array<{ killerId: string; victimId: string; round: number; timestamp: number }> = [];

        // 计算所有参与者的统计数据
        const allParticipants = [...context.state.homeParticipants, ...context.state.awayParticipants];
        
        for (const participant of allParticipants) {
            const stats: ParticipantStats = {
                participantId: participant.id,
                damageDealt: 0,
                damageTaken: 0,
                healingDone: 0,
                healingReceived: 0,
                kills: 0,
                deaths: participant.isAlive ? 0 : 1,
                skillsUsed: 0,
                actionsPerformed: 0,
                roundsSurvived: participant.isAlive ? context.state.currentRound : this.calculateSurvivalRounds(context, participant.id)
            };

            // 从事件历史中统计数据
            for (const event of context.eventHistory) {
                this.processEventForStats(event, participant.id, stats);
            }

            participantStats.set(participant.id, stats);
        }

        // 计算击杀统计
        for (const event of context.eventHistory) {
            if (event.type === 'battle.unit.died' && event.data.killerId) {
                kills.push({
                    killerId: event.data.killerId,
                    victimId: event.data.unitId,
                    round: event.round,
                    timestamp: event.timestamp
                });

                // 更新击杀者的击杀数
                const killerStats = participantStats.get(event.data.killerId);
                if (killerStats) {
                    killerStats.kills++;
                }
            }
        }

        // 计算总体统计
        let totalDamage = 0;
        let totalHealing = 0;
        for (const stats of participantStats.values()) {
            totalDamage += stats.damageDealt;
            totalHealing += stats.healingDone;
        }

        const duration = context.state.endTime 
            ? context.state.endTime - context.state.startTime 
            : Date.now() - context.state.startTime;

        return {
            participantStats,
            totalRounds: context.state.currentRound,
            duration,
            totalDamage,
            totalHealing,
            kills
        };
    }

    /**
     * 确定战斗结果
     */
    private determineResult(context: BattleContext): { resultType: BattleResultType; winner?: 'home' | 'away' } {
        const stateManager = new BattleStateManager();
        
        // 检查是否被取消
        if (context.state.status === 'cancelled') {
            return { resultType: BattleResultType.CANCELLED };
        }

        // 检查是否超时
        const duration = Date.now() - context.state.startTime;
        if (context.rules.timeoutRules.enabled && duration > context.rules.timeoutRules.maxDuration) {
            return { resultType: BattleResultType.TIMEOUT };
        }

        // 检查获胜方
        const winner = stateManager.getWinner(context);
        
        if (winner === 'home' || winner === 'away') {
            return { resultType: BattleResultType.VICTORY, winner };
        } else if (winner === 'draw') {
            return { resultType: BattleResultType.DRAW };
        }

        // 默认为平局
        return { resultType: BattleResultType.DRAW };
    }

    /**
     * 生成奖励
     */
    private async generateRewards(
        context: BattleContext, 
        resultType: BattleResultType, 
        winner?: 'home' | 'away'
    ): Promise<Map<string, Item[]>> {
        const rewards = new Map<string, Item[]>();
        
        // 如果战斗被取消或出错，不给奖励
        if (resultType === BattleResultType.CANCELLED) {
            return rewards;
        }

        const config = this.defaultRewardConfig;
        
        // 确定获得奖励的参与者
        let rewardRecipients: string[] = [];
        
        if (resultType === BattleResultType.VICTORY && winner) {
            // 胜利方获得奖励
            const winningParticipants = winner === 'home' 
                ? context.state.homeParticipants 
                : context.state.awayParticipants;
            rewardRecipients = winningParticipants.map(p => p.id);
        } else if (resultType === BattleResultType.DRAW) {
            // 平局时所有参与者获得部分奖励
            rewardRecipients = [...context.state.homeParticipants, ...context.state.awayParticipants].map(p => p.id);
        }

        // 为每个获奖者生成奖励
        for (const participantId of rewardRecipients) {
            const participantRewards: Item[] = [];

            // 基础金币奖励
            const goldAmount = Math.floor(config.baseGold * config.goldMultiplier * this.getRewardMultiplier(resultType, winner));
            if (goldAmount > 0) {
                participantRewards.push({
                    itemId: 'gold',
                    count: goldAmount,
                    name: '金币',
                    description: '战斗奖励金币'
                });
            }

            // 物品掉落
            if (Math.random() < config.itemDropChance) {
                const droppedItems = this.generateRandomItems(config.maxDropItems);
                participantRewards.push(...droppedItems);
            }

            rewards.set(participantId, participantRewards);
        }

        this.logger.debug(`Rewards generated for ${rewards.size} participants`);
        return rewards;
    }

    /**
     * 计算经验分配
     */
    private calculateExperience(
        context: BattleContext, 
        resultType: BattleResultType, 
        winner?: 'home' | 'away'
    ): Map<string, number> {
        const experience = new Map<string, number>();
        
        if (resultType === BattleResultType.CANCELLED) {
            return experience;
        }

        const config = this.defaultRewardConfig;
        const baseExp = config.baseExperience;
        const multiplier = this.getRewardMultiplier(resultType, winner);

        // 所有参与者都获得基础经验（活跃参与的奖励）
        const allParticipants = [...context.state.homeParticipants, ...context.state.awayParticipants];
        
        for (const participant of allParticipants) {
            let expAmount = Math.floor(baseExp * multiplier);
            
            // 根据参与度调整经验
            const participationMultiplier = this.calculateParticipationMultiplier(context, participant.id);
            expAmount = Math.floor(expAmount * participationMultiplier);
            
            // 存活奖励
            if (participant.isAlive) {
                expAmount = Math.floor(expAmount * 1.2);
            }

            experience.set(participant.id, expAmount);
        }

        this.logger.debug(`Experience calculated for ${experience.size} participants`);
        return experience;
    }

    /**
     * 生成战斗报告
     */
    private async generateBattleReport(context: BattleContext, statistics: BattleStatistics): Promise<string> {
        try {
            // 这里应该实际生成并上传战斗报告
            // 暂时返回一个模拟的URL
            const reportId = `report_${context.state.battleId}_${Date.now()}`;
            const reportUrl = `https://example.com/battle-reports/${reportId}`;
            
            this.logger.debug(`Battle report generated: ${reportUrl}`);
            return reportUrl;
            
        } catch (error) {
            this.logger.error('Failed to generate battle report', undefined, error);
            return '';
        }
    }

    /**
     * 生成错误结果
     */
    private generateErrorResult(context: BattleContext, error: Error): BattleResult {
        return {
            battleId: context.state.battleId,
            resultType: BattleResultType.CANCELLED,
            statistics: {
                participantStats: new Map(),
                totalRounds: context.state.currentRound,
                duration: Date.now() - context.state.startTime,
                totalDamage: 0,
                totalHealing: 0,
                kills: []
            },
            rewards: new Map(),
            experience: new Map(),
            completedAt: Date.now(),
            failureReason: error.message
        };
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 处理事件以更新统计数据
     */
    private processEventForStats(event: any, participantId: string, stats: ParticipantStats): void {
        switch (event.type) {
            case 'battle.unit.damaged':
                if (event.data.attackerId === participantId) {
                    stats.damageDealt += event.data.damage;
                }
                if (event.data.targetId === participantId) {
                    stats.damageTaken += event.data.damage;
                }
                break;

            case 'battle.unit.healed':
                if (event.data.healerId === participantId) {
                    stats.healingDone += event.data.healing;
                }
                if (event.data.targetId === participantId) {
                    stats.healingReceived += event.data.healing;
                }
                break;

            case 'battle.unit.skill_used':
                if (event.data.casterId === participantId) {
                    stats.skillsUsed++;
                }
                break;

            case 'battle.unit.action':
                if (event.data.actorId === participantId) {
                    stats.actionsPerformed++;
                }
                break;
        }
    }

    /**
     * 计算存活回合数
     */
    private calculateSurvivalRounds(context: BattleContext, participantId: string): number {
        // 从事件历史中找到死亡事件
        for (const event of context.eventHistory) {
            if (event.type === 'battle.unit.died' && event.data.unitId === participantId) {
                return event.round;
            }
        }
        return context.state.currentRound;
    }

    /**
     * 获取奖励倍数
     */
    private getRewardMultiplier(resultType: BattleResultType, winner?: 'home' | 'away'): number {
        switch (resultType) {
            case BattleResultType.VICTORY:
                return 1.0;
            case BattleResultType.DRAW:
                return 0.5;
            case BattleResultType.DEFEAT:
                return 0.3;
            case BattleResultType.TIMEOUT:
                return 0.2;
            default:
                return 0.1;
        }
    }

    /**
     * 计算参与度倍数
     */
    private calculateParticipationMultiplier(context: BattleContext, participantId: string): number {
        let actionCount = 0;
        let totalActions = 0;

        for (const event of context.eventHistory) {
            if (event.type === 'battle.unit.action') {
                totalActions++;
                if (event.data.actorId === participantId) {
                    actionCount++;
                }
            }
        }

        if (totalActions === 0) return 1.0;

        const participationRate = actionCount / totalActions;
        return Math.max(0.5, Math.min(1.5, 0.5 + participationRate));
    }

    /**
     * 生成随机物品
     */
    private generateRandomItems(maxItems: number): Item[] {
        const items: Item[] = [];
        const itemPool = [
            { itemId: 'potion_health', name: '生命药水', description: '恢复生命值' },
            { itemId: 'potion_mana', name: '法力药水', description: '恢复法力值' },
            { itemId: 'scroll_buff', name: '增益卷轴', description: '提供临时增益' },
            { itemId: 'gem_small', name: '小宝石', description: '可以镶嵌的宝石' }
        ];

        const itemCount = Math.floor(Math.random() * maxItems) + 1;
        
        for (let i = 0; i < itemCount; i++) {
            const randomItem = itemPool[Math.floor(Math.random() * itemPool.length)];
            items.push({
                ...randomItem,
                count: Math.floor(Math.random() * 3) + 1
            });
        }

        return items;
    }
}
